#pragma once
#include "gtest/gtest.h"

#include "DataStructure/Common/Real.h"
#include "DataStructure/Input/Element/CHEXAData.h"
#include "DataStructure/Input/Solver/DOFDirections.h"
#include "DataStructure/Input/Material/IsotropicMaterial.h"
#include "DataStructure/Input/Solver/TenserTranform.h"

#include "DBManager/DBServiceFactory.h"
#include "DBManager/IService/Input/Subcase/ISubcaseService.h"

#include "SGFem/Pre/Assembly/Assembly.h"
#include "SGFem/Pre/Assembly/CoordinateProcessor.h"

#include "../../Factory/ElementCalculatorFactory.h"
#include "../Hexa8SRIElementCalculator.h"

using SG::Algebra::Matrixd;
using SG::Algebra::Point;
using SG::Algebra::Vector3D;
using SG::DataStructure::Common::Real;
using namespace SG::DataStructure::FEM;
using namespace SG::DBManager;
using SG::FEMSolver::AssemblyEigen;
using SG::FEMSolver::CoordinateProcessor;
using SG::FEMSolver::Element::ElementCalculatorFactory;
using SG::FEMSolver::Element::Hexa8SRIElementCalculator;
using SG::DataStructure::FEM::ElementTypes;

// ElementCalculatorFactory 是否正确创建 Hexa8 单元计算类
TEST (ElementCalculatorFactoryTest, CreateHexa8SRICalculator)
{
    ElementCalculatorFactory::Register (ElementTypes::ELETYPE_Hexa8SRI, Hexa8SRIElementCalculator::Create);

    // Test data
    const auto calculatorPtr         = ElementCalculatorFactory::Create (ElementTypes::ELETYPE_Hexa8SRI);
    const auto Hexa8SRICalculatorPtr = dynamic_cast<Hexa8SRIElementCalculator*> (calculatorPtr.get ());

    // Check
    ASSERT_TRUE (nullptr != Hexa8SRICalculatorPtr);
}

extern std::shared_ptr<DBServiceFactory> DB_SERVICEFACTORY;
class Hexa8CalculatorTest : public ::testing::Test
{
protected:
    static void SetUpTestSuite ()
    {
        DB_SERVICEFACTORY->ClearDatabase ();

        // 直角坐标系 100
        CORD2RData rectangularCoordSys{100, 0, {1.0, 2.0, 3.0}, {2.0, 4.0, 1.0}, {5.0, 1.0, 1.0}};
        DB_SERVICEFACTORY->get<ICORD2RService> ()->Add (rectangularCoordSys);

        // 生成节点排序
        auto& assembly = AssemblyEigen::GetInstance ();
        assembly.Clear ();
        Subcase subcase;
        assembly.Initialize (DB_SERVICEFACTORY, subcase, {1});

        // 计算坐标系原点和基矢量
        auto& coordProcessor = CoordinateProcessor::GetInstance ();
        coordProcessor.Clear ();
        coordProcessor.Initialize (DB_SERVICEFACTORY);
    }

    void SetUp () override
    {
        E = 11000000.0;
        nu = 0.25;
        G = E / (2.0 * (1.0 + nu));
        lame = nu * E / (1 - 2.0 * nu) / (1 + nu);
        D = Matrixd (6, 6);
        D (0, 0) = lame + G * 2.0; D (0, 1) = lame;           D (0, 2) = lame;
        D (1, 0) = lame;           D (1, 1) = lame + G * 2.0; D (1, 2) = lame;
        D (2, 0) = lame;           D (2, 1) = lame;           D (2, 2) = lame + G * 2.0;
        D (3, 3) = G;
        D (4, 4) = G;
        D (5, 5) = G;

        pointSet = {Point{0.249, 0.342, 0.192}, Point{0.826, 0.288, 0.288}, Point{0.85, 0.649, 0.263}, Point{0.273, 0.75, 0.23},
        Point{0.32, 0.286, 0.643},Point{0.677, 0.305, 0.683},Point{0.788, 0.693, 0.644},Point{0.165, 0.745, 0.702},
        Point{1.0, 0.0, 1.0},Point{1.0, 1.0, 1.0},Point{1.0, 1.0, 0.0},Point{1.0, 0.0, 0.0},Point{0.0, 1.0, 1.0},
        Point{0.0, 1.0, 0.0},Point{0.0, 0.0, 0.0},Point{0.0, 0.0, 1.0}};
        T = SG::Algebra::identity (3);
        localCoord = Matrixd (3, 4, {
        0.0, 0.0, 0.9, 0.0,
        0.0, 0.8, 0.0, 0.0,
        0.0, 0.0, 0.0, 0.7
        });

        eleDisplacement = Matrixd (48, 1, {
        0.51600E-3,           0.56250E-3,             0.48750E-3,
        0.11140E-2,           0.84500E-3,             0.84500E-3,
        0.13060E-2,           0.12055E-2,             0.10125E-2,
        0.76300E-3,           0.10015E-2,             0.74150E-3,
        0.78450E-3,           0.76750E-3,             0.94600E-3,
        0.11710E-2,           0.98500E-3,             0.11740E-2,
        0.14565E-2,           0.14090E-2,             0.13845E-2,
        0.88850E-3,           0.11785E-2,             0.11570E-2,
        0.15000E-2,           0.10000E-2,             0.15000E-2,
        0.20000E-2,           0.20000E-2,             0.20000E-2,
        0.15000E-2,           0.15000E-2,             0.10000E-2,
        0.10000E-2,           0.50000E-3,             0.50000E-3,
        0.10000E-2,           0.15000E-2,             0.15000E-2,
        0.50000E-3,           0.10000E-2,             0.50000E-3,
        0.0,                  0.0,                    0.0,
        0.50000E-3,           0.50000E-3,             0.10000E-2
        });

        eleCalculator.Initialize (ElementTypes::ELETYPE_Tetra4);

        // 小量放大系数
        factor = 1.0E6;
    }

    Real E, nu, rho, G, lame;
    Matrixd D;
    PointArray pointSet;
    PSOLIDData property;
    Matrixd T;
    Matrixd localCoord;
    Matrixd eleDisplacement;
    Tetra4ElementCalculator eleCalculator;
    Real factor;
};

//测试刚度矩阵
TEST_F (Hexa8CalculatorTest, ComputeStiffness)
{
    // Input data
    IsotropicMaterial material;
    material.m_E  = 1000000;
    material.m_nu = 0.25;
    material.m_G  = 400000;

    // 计算材料的本构矩阵
    G   = material.m_G;
    E   = material.m_E;   //<杨氏模量
    nu  = material.m_nu;  //<泊松比
    lame = E * nu / (1.0 + nu) / (1.0 - 2.0 * nu);
    D (0, 0) = D (1, 1) = D (2, 2) = lame + 2 * G;
    D (3, 3) = D (4, 4) = D (5, 5) = G;
    D (0, 1) = D (1, 0) = D (0, 2) = D (2, 0) = D (1, 2) = D (2, 1) = lame;

    localCoord = Matrixd (8,
                          3,
                          {
                              0.32,  0.286, 0.643, 0.677, 0.305, 0.683, 0.826, 0.288, 0.288, 0.249, 0.342, 0.192,
                              0.165, 0.745, 0.702, 0.788, 0.693, 0.644, 0.85,  0.649, 0.263, 0.273, 0.75,  0.23,
                          });
    localCoord = localCoord.Transpose();

    // Test data
    Matrixd                 kTest (24, 24);
    Hexa8SRIElementCalculator eleCalculator;
    eleCalculator.Initialize(SG::DataStructure::FEM::ElementTypes::ELETYPE_Hexa8SRI);
    eleCalculator.ComputeStiffness (localCoord, D, _OUT kTest);
    // Target data 一行6个数，4行代表原刚度阵1行
    Matrixd kTarget (
        24,
        24,
        {
            0.9591746E+05,  0.3434084E+05,  -0.2823322E+05, -0.1872272E+05, -0.1094378E+04, -0.2700178E+04, -0.2841725E+05, 0.4510356E+04,
            0.2387524E+05,  0.1776520E+05,  0.1718964E+05,  0.5406841E+04,  0.1289798E+05,  0.1307387E+04,  -0.1638119E+05, -0.3735939E+05,
            -0.3210713E+05, -0.4455232E+04, -0.3923425E+05, -0.1879213E+05, 0.1387424E+05,  -0.2847019E+04, -0.5354576E+04, 0.8613503E+04,
            0.3434084E+05,  0.1166145E+06,  -0.3189208E+05, 0.1687167E+04,  0.2047520E+05,  -0.1506685E+05, 0.1619357E+04,  0.9669660E+04,
            0.1558480E+04,  0.1741402E+05,  0.2847995E+05,  0.3269859E+04,  -0.1357886E+04, -0.4285691E+05, -0.4243877E+04, -0.3168283E+05,
            -0.4171864E+05, -0.6748286E+04, -0.1883720E+05, -0.3879176E+05, 0.1701837E+05,  -0.3183467E+04, -0.5187204E+05, 0.3610438E+05,
            -0.2823322E+05, -0.3189208E+05, 0.9314529E+05,  -0.5155091E+04, -0.1445742E+05, 0.1750750E+05,  0.2396756E+05,  -0.1632395E+04,
            -0.2501799E+05, 0.7740314E+04,  0.5948342E+04,  -0.2957881E+05, -0.1605285E+05, -0.6911661E+04, 0.1607219E+05,  -0.1903172E+04,
            -0.3638280E+04, 0.4534303E+04,  0.1338530E+05,  0.1648606E+05,  -0.3422514E+05, 0.6251160E+04,  0.3609743E+05,  -0.4243735E+05,
            -0.1872272E+05, 0.1687167E+04,  -0.5155091E+04, 0.7791219E+05,  -0.2130471E+05, 0.2039137E+05,  0.8805167E+04,  -0.1362517E+05,
            0.6089358E+04,  -0.2363579E+05, 0.1934306E+04,  -0.2676487E+05, -0.2305086E+05, 0.2266429E+05,  -0.5499372E+01, 0.1145013E+05,
            -0.1963185E+04, 0.1382230E+05,  -0.2080221E+04, -0.2023806E+04, 0.6304376E+04,  -0.3067789E+05, 0.1263111E+05,  -0.1468195E+05,
            -0.1094378E+04, 0.2047520E+05,  -0.1445742E+05, -0.2130471E+05, 0.1001825E+06,  -0.3686242E+05, -0.1233757E+05, 0.2525242E+05,
            -0.8623611E+04, 0.4004335E+04,  0.7762279E+04,  0.2006411E+04,  0.2337435E+05,  -0.3292534E+05, 0.9544347E+03,  0.2306391E+03,
            -0.3684419E+05, 0.2309366E+04,  -0.4770353E+04, -0.4400206E+05, 0.3345352E+05,  0.1189769E+05,  -0.3990086E+05, 0.2121972E+05,
            -0.2700178E+04, -0.1506685E+05, 0.1750750E+05,  0.2039137E+05,  -0.3686242E+05, 0.1055836E+06,  0.3467260E+04,  -0.4739244E+04,
            -0.3225071E+05, -0.2706509E+05, -0.1237072E+04, -0.4074122E+05, -0.1838202E+04, 0.4004623E+04,  0.7921993E+04,  0.1363307E+05,
            -0.1408565E+04, 0.2720043E+05,  0.8430819E+04,  0.3353480E+05,  -0.4396544E+05, -0.1431904E+05, 0.2177472E+05,  -0.4125617E+05,
            -0.2841725E+05, 0.1619357E+04,  0.2396756E+05,  0.8805167E+04,  -0.1233757E+05, 0.3467260E+04,  0.7585918E+05,  -0.2753261E+05,
            -0.2459238E+05, -0.5849216E+04, 0.4110854E+04,  -0.5517363E+03, -0.2866909E+05, 0.1238793E+05,  0.1046348E+05,  -0.3428736E+04,
            0.2441807E+04,  0.3825396E+04,  0.4845150E+04,  -0.5599490E+04, -0.1334112E+05, -0.2314520E+05, 0.2490972E+05,  -0.3238462E+04,
            0.4510356E+04,  0.9669660E+04,  -0.1632395E+04, -0.1362517E+05, 0.2525242E+05,  -0.4739244E+04, -0.2753261E+05, 0.1065148E+06,
            0.3118454E+05,  0.1851679E+04,  0.3451954E+05,  0.2020718E+05,  0.1290771E+05,  -0.3404367E+05, -0.1668395E+05, -0.6497668E+02,
            -0.4922586E+05, -0.3365261E+05, -0.2692698E+04, -0.5357017E+05, 0.1318071E+04,  0.2464570E+05,  -0.3911676E+05, 0.3998402E+04,
            0.2387524E+05,  0.1558480E+04,  -0.2501799E+05, 0.6089358E+04,  -0.8623611E+04, -0.3225071E+05, -0.2459238E+05, 0.3118454E+05,
            0.8225086E+05,  -0.3033347E+04, 0.2011798E+05,  0.3255591E+05,  0.1018494E+05,  -0.1565345E+05, -0.3046399E+05, 0.1102592E+04,
            -0.3400475E+05, -0.4408866E+05, -0.1289465E+05, 0.4281356E+04,  0.8775397E+04,  -0.7317449E+03, 0.1139455E+04,  0.8239191E+04,
            0.1776520E+05,  0.1741402E+05,  0.7740314E+04,  -0.2363579E+05, 0.4004335E+04,  -0.2706509E+05, -0.5849216E+04, 0.1851679E+04,
            -0.3033347E+04, 0.8173415E+05,  0.2645412E+05,  0.2730086E+05,  -0.2638660E+04, -0.4187833E+02, 0.1398568E+04,  -0.3578267E+05,
            -0.1723992E+05, -0.1916703E+05, -0.3604604E+05, -0.2881823E+05, -0.1973837E+04, 0.4453029E+04,  -0.3624128E+04, 0.1479956E+05,
            0.1718964E+05,  0.2847995E+05,  0.5948342E+04,  0.1934306E+04,  0.7762279E+04,  -0.1237072E+04, 0.4110854E+04,  0.3451954E+05,
            0.2011798E+05,  0.2645412E+05,  0.1025866E+06,  0.3509958E+05,  0.1977330E+04,  -0.4147766E+05, -0.3152975E+05, -0.1735215E+05,
            -0.4004313E+05, -0.2276424E+05, -0.2903766E+05, -0.3912719E+05, -0.3023005E+04, -0.5276438E+04, -0.5270044E+05, -0.2611829E+04,
            0.5406841E+04,  0.3269859E+04,  -0.2957881E+05, -0.2676487E+05, 0.2006411E+04,  -0.4074122E+05, -0.5517363E+03, 0.2020718E+05,
            0.3255591E+05,  0.2730086E+05,  0.3509958E+05,  0.1022881E+06,  0.3097558E+04,  -0.3231959E+05, -0.4442880E+05, -0.1929569E+05,
            -0.2255623E+05, -0.4525101E+05, -0.3939514E+04, -0.5494827E+04, 0.5528322E+04,  0.1474655E+05,  -0.2123830E+03, 0.1962752E+05,
            0.1289798E+05,  -0.1357886E+04, -0.1605285E+05, -0.2305086E+05, 0.2337435E+05,  -0.1838202E+04, -0.2866909E+05, 0.1290771E+05,
            0.1018494E+05,  -0.2638660E+04, 0.1977330E+04,  0.3097558E+04,  0.6714710E+05,  -0.2542843E+05, -0.2342027E+05, -0.8588046E+04,
            0.3093722E+04,  0.1524006E+04,  -0.2389193E+05, 0.6101775E+03,  0.2304466E+05,  0.6793514E+04,  -0.1517697E+05, 0.3460155E+04,
            0.1307387E+04,  -0.4285691E+05, -0.6911661E+04, 0.2266429E+05,  -0.3292534E+05, 0.4004623E+04,  0.1238793E+05,  -0.3404367E+05,
            -0.1565345E+05, -0.4187833E+02, -0.4147766E+05, -0.3231959E+05, -0.2542843E+05, 0.8235054E+05,  0.2874534E+05,  0.8869890E+03,
            0.3475223E+05,  0.2017858E+05,  0.3274024E+04,  0.1298231E+05,  -0.1212832E+04, -0.1505031E+05, 0.2121850E+05,  0.3168993E+04,
            -0.1638119E+05, -0.4243877E+04, 0.1607219E+05,  -0.5499372E+01, 0.9544347E+03,  0.7921993E+04,  0.1046348E+05,  -0.1668395E+05,
            -0.3046399E+05, 0.1398568E+04,  -0.3152975E+05, -0.4442880E+05, -0.2342027E+05, 0.2874534E+05,  0.8287162E+05,  -0.3554141E+03,
            0.2088784E+05,  0.3254874E+05,  0.2312804E+05,  0.1092961E+04,  -0.2190731E+05, 0.5172274E+04,  0.7769953E+03,  -0.4261444E+05,
            -0.3735939E+05, -0.3168283E+05, -0.1903172E+04, 0.1145013E+05,  0.2306391E+03,  0.1363307E+05,  -0.3428736E+04, -0.6497668E+02,
            0.1102592E+04,  -0.3578267E+05, -0.1735215E+05, -0.1929569E+05, -0.8588046E+04, 0.8869890E+03,  -0.3554141E+03, 0.9038330E+05,
            0.2749290E+05,  0.2984517E+05,  0.1089851E+05,  0.1588483E+05,  0.4754497E+04,  -0.2757308E+05, 0.4604606E+04,  -0.2778105E+05,
            -0.3210713E+05, -0.4171864E+05, -0.3638280E+04, -0.1963185E+04, -0.3684419E+05, -0.1408565E+04, 0.2441807E+04,  -0.4922586E+05,
            -0.3400475E+05, -0.1723992E+05, -0.4004313E+05, -0.2255623E+05, 0.3093722E+04,  0.3475223E+05,  0.2088784E+05,  0.2749290E+05,
            0.1033787E+06,  0.3743143E+05,  0.1547065E+05,  0.2106054E+05,  0.3435073E+04,  0.2811163E+04,  0.8640399E+04,  -0.1465218E+03,
            -0.4455232E+04, -0.6748286E+04, 0.4534303E+04,  0.1382230E+05,  0.2309366E+04,  0.2720043E+05,  0.3825396E+04,  -0.3365261E+05,
            -0.4408866E+05, -0.1916703E+05, -0.2276424E+05, -0.4525101E+05, 0.1524006E+04,  0.2017858E+05,  0.3254874E+05,  0.2984517E+05,
            0.3743143E+05,  0.1124885E+06,  0.2577462E+04,  0.6063086E+03,  -0.4123288E+05, -0.2797207E+05, 0.2639458E+04,  -0.4619938E+05,
            -0.3923425E+05, -0.1883720E+05, 0.1338530E+05,  -0.2080221E+04, -0.4770353E+04, 0.8430819E+04,  0.4845150E+04,  -0.2692698E+04,
            -0.1289465E+05, -0.3604604E+05, -0.2903766E+05, -0.3939514E+04, -0.2389193E+05, 0.3274024E+04,  0.2312804E+05,  0.1089851E+05,
            0.1547065E+05,  0.2577462E+04,  0.8758577E+05,  0.3161480E+05,  -0.2634061E+05, -0.2076972E+04, 0.4978437E+04,  -0.4346849E+04,
            -0.1879213E+05, -0.3879176E+05, 0.1648606E+05,  -0.2023806E+04, -0.4400206E+05, 0.3353480E+05,  -0.5599490E+04, -0.5357017E+05,
            0.4281356E+04,  -0.2881823E+05, -0.3912719E+05, -0.5494827E+04, 0.6101775E+03,  0.1298231E+05,  0.1092961E+04,  0.1588483E+05,
            0.2106054E+05,  0.6063086E+03,  0.3161480E+05,  0.1017410E+06,  -0.2949147E+05, 0.7123855E+04,  0.3970730E+05,  -0.2101518E+05,
            0.1387424E+05,  0.1701837E+05,  -0.3422514E+05, 0.6304376E+04,  0.3345352E+05,  -0.4396544E+05, -0.1334112E+05, 0.1318071E+04,
            0.8775397E+04,  -0.1973837E+04, -0.3023005E+04, 0.5528322E+04,  0.2304466E+05,  -0.1212832E+04, -0.2190731E+05, 0.4754497E+04,
            0.3435073E+04,  -0.4123288E+05, -0.2634061E+05, -0.2949147E+05, 0.9251787E+05,  -0.6322208E+04, -0.2149773E+05, 0.3450917E+05,
            -0.2847019E+04, -0.3183467E+04, 0.6251160E+04,  -0.3067789E+05, 0.1189769E+05,  -0.1431904E+05, -0.2314520E+05, 0.2464570E+05,
            -0.7317449E+03, 0.4453029E+04,  -0.5276438E+04, 0.1474655E+05,  0.6793514E+04,  -0.1505031E+05, 0.5172274E+04,  -0.2757308E+05,
            0.2811163E+04,  -0.2797207E+05, -0.2076972E+04, 0.7123855E+04,  -0.6322208E+04, 0.7507363E+05,  -0.2296820E+05, 0.2317509E+05,
            -0.5354576E+04, -0.5187204E+05, 0.3609743E+05,  0.1263111E+05,  -0.3990086E+05, 0.2177472E+05,  0.2490972E+05,  -0.3911676E+05,
            0.1139455E+04,  -0.3624128E+04, -0.5270044E+05, -0.2123830E+03, -0.1517697E+05, 0.2121850E+05,  0.7769953E+03,  0.4604606E+04,
            0.8640399E+04,  0.2639458E+04,  0.4978437E+04,  0.3970730E+05,  -0.2149773E+05, -0.2296820E+05, 0.1140239E+06,  -0.4071795E+05,
            0.8613503E+04,  0.3610438E+05,  -0.4243735E+05, -0.1468195E+05, 0.2121972E+05,  -0.4125617E+05, -0.3238462E+04, 0.3998402E+04,
            0.8239191E+04,  0.1479956E+05,  -0.2611829E+04, 0.1962752E+05,  0.3460155E+04,  0.3168993E+04,  -0.4261444E+05, -0.2778105E+05,
            -0.1465218E+03, -0.4619938E+05, -0.4346849E+04, -0.2101518E+05, 0.3450917E+05,  0.2317509E+05,  -0.4071795E+05, 0.1101315E+06,
        });
     
    // Check
    ASSERT_TRUE (kTest == kTarget);
}

